package com.ray.test.proxy;

import com.alibaba.fastjson.annotation.JSONField;
import com.ray.test.annotation.Mock;
import com.ray.test.annotation.MockData;
import com.ray.test.serializable.ProtostuffSerializable;
import com.ray.test.serializable.Serializable;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.junit.runners.model.FrameworkMethod;

import java.lang.reflect.Field;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author bo shen
 * @Description: 配置
 * @Class: MockTestConfig
 * @Package com.ray.test.proxy
 * @date 2019/12/19 17:58
 * @company <p>杭州传化陆鲸科技有限公司</p>
 * @updateRecord time(修改时间)  author(修改人)   desc(修改内容)
 */
@Data
@Slf4j
public class MockTestConfig implements java.io.Serializable{
    /***是否刷新数据**/
    private boolean reflush = false;
    /***是否有数据**/
    private boolean hasData = false;
    /**方法名称**/
    private String name;
    /**是否走mock***/
    private boolean mock = false;
    /***数据存存储路径**/
    private String dataPath;
    /***测试文件目录**/
    private String testRoot;
    /***类名称**/
    private String className = "default";
    /***默认序列化**/
    private  Class<?> mockDataType = ProtostuffSerializable.class;
    @JSONField(serialize=false)
    public transient AtomicInteger integer = new AtomicInteger(0);
    /***模拟的数据***/
     @JSONField(serialize=false)
    private transient com.ray.test.proxy.MockData mockData = new com.ray.test.proxy.MockData();

    @JSONField(serialize=false)
    private  transient static  ThreadLocal<MockTestConfig> mockTestConfig = new ThreadLocal<>();
    /**
     * 获取一个配置
     * @param frameworkMethod
     * @return
     */
    public static void set(FrameworkMethod frameworkMethod,Class<?> clazz) {
        try {
            MockTestConfig config = new MockTestConfig();
            log.info("读取{}配置",frameworkMethod.getName());
            Boolean groupMockData = getGroupMockData(clazz);
            Class<?> dataType =  getGroupMockDataType(clazz);
            Serializable serializable = (Serializable)dataType.newInstance();
            MockData mockData = frameworkMethod.getAnnotation(MockData.class);
            if(mockData != null){
                config.setMock(mockData.value() && groupMockData);
                config.setDataPath(mockData.dataPath());
                config.setTestRoot(mockData.testRoot());
                config.setName(frameworkMethod.getName());
                config.setClassName(clazz.getName());
                config.setMockDataType(dataType);
                config = serializable.get(config);
            }
            //读取mockData数据
            mockTestConfig.set(config);
        }catch (Exception e){
            log.info("初始化数据失败:{}",e.getMessage());
            throw  new RuntimeException(e.getMessage());
        }
    }

    private static Boolean getGroupMockData(Class<?> clazz) {
         for(Field field :  clazz.getDeclaredFields()){
             Mock mock = field.getAnnotation(Mock.class);
             if(mock != null){
                 return  mock.mackData();
             }
         }
        return true;
    }

    private static Class<?> getGroupMockDataType(Class<?> clazz) {
        for(Field field :  clazz.getDeclaredFields()){
            Mock mock = field.getAnnotation(Mock.class);
            if(mock != null){
                return  mock.mockDataType();
            }
        }
        return null;
    }

    /**
     * 清理配置
     * @return
     */
    public static void clearConfig() {
        mockTestConfig.set(null);
    }

    public static MockTestConfig get() {
       return mockTestConfig.get();
    }

    public void setMockData(com.ray.test.proxy.MockData mockData) {
        this.mockData = mockData;
    }

    public String getFilePath(){
        String root = this.getClass().getResource("/").getPath();
        return  String.format("%s%s/%s/%s",root,dataPath,className,name);
    }

    public String getSourcePath(){
        String root = this.getClass().getResource("/").getPath();
        root  = root.substring(0,root.lastIndexOf("/target"));
        return  String.format("%s/%s/%s/%s/%s",root,testRoot,dataPath,className,name);
    }
}
